package com.yiyahui.project.erp.service.impl;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.yiyahui.common.utils.DateUtils;
import com.yiyahui.framework.web.domain.AjaxResult;
import com.yiyahui.project.erp.domain.*;
import com.yiyahui.project.erp.domain.requestVo.ModeAndMoney;
import com.yiyahui.project.erp.domain.requestVo.PayMoneyRequest;
import com.yiyahui.project.erp.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.yiyahui.project.erp.mapper.YiyaClosingMethodsMapper;
import org.springframework.transaction.annotation.Transactional;

import static org.assertj.core.util.DateUtil.now;

/**
 * 主单结账流水方式Service业务层处理
 * 
 * @author yiyahui
 * @date 2020-06-10
 */
@Service
public class YiyaClosingMethodsServiceImpl implements IYiyaClosingMethodsService 
{
    @Autowired
    private YiyaClosingMethodsMapper yiyaClosingMethodsMapper;

    @Autowired
    private IYiyaMainClosingEntriesService yiyaMainClosingEntriesService;

    @Autowired
    private IYiyaBillingMainService yiyaBillingMainService;

    @Autowired
    private IYiyaItemBillingService yiyaItemBillingService;

    @Autowired
    private IYiyaClosingWaterRelationService yiyaClosingWaterRelationService;

    @Autowired
    private IYiyaClinicPersonService yiyaClinicPersonService;

    @Autowired
    private IYiyaMarketReservationService yiyaMarketReservationService;

    @Autowired
    private IYiyaStatisticsItemService yiyaStatisticsItemService;

    @Autowired
    private IYiyaStatisticsModePayService yiyaStatisticsModePayService;

    @Autowired
    private IYiyaChargeProjectService yiyaChargeProjectService;

    /**
     * 查询主单结账流水方式
     * 
     * @param id 主单结账流水方式ID
     * @return 主单结账流水方式
     */
    @Override
    public YiyaClosingMethods selectYiyaClosingMethodsById(Long id)
    {
        return yiyaClosingMethodsMapper.selectYiyaClosingMethodsById(id);
    }

    /**
     * 查询主单结账流水方式列表
     * 
     * @param yiyaClosingMethods 主单结账流水方式
     * @return 主单结账流水方式
     */
    @Override
    public List<YiyaClosingMethods> selectYiyaClosingMethodsList(YiyaClosingMethods yiyaClosingMethods)
    {
        return yiyaClosingMethodsMapper.selectYiyaClosingMethodsList(yiyaClosingMethods);
    }

    /**
     * 新增主单结账流水方式
     * 
     * @param yiyaClosingMethods 主单结账流水方式
     * @return 结果
     */
    @Override
    public int insertYiyaClosingMethods(YiyaClosingMethods yiyaClosingMethods)
    {
        yiyaClosingMethods.setCreateTime(DateUtils.getNowDate());
        return yiyaClosingMethodsMapper.insertYiyaClosingMethods(yiyaClosingMethods);
    }

    /**
     * 修改主单结账流水方式
     * 
     * @param yiyaClosingMethods 主单结账流水方式
     * @return 结果
     */
    @Override
    public int updateYiyaClosingMethods(YiyaClosingMethods yiyaClosingMethods)
    {
        yiyaClosingMethods.setUpdateTime(DateUtils.getNowDate());
        return yiyaClosingMethodsMapper.updateYiyaClosingMethods(yiyaClosingMethods);
    }

    /**
     * 批量删除主单结账流水方式
     * 
     * @param ids 需要删除的主单结账流水方式ID
     * @return 结果
     */
    @Override
    public int deleteYiyaClosingMethodsByIds(Long[] ids)
    {
        return yiyaClosingMethodsMapper.deleteYiyaClosingMethodsByIds(ids);
    }

    /**
     * 删除主单结账流水方式信息
     * 
     * @param id 主单结账流水方式ID
     * @return 结果
     */
    @Override
    public int deleteYiyaClosingMethodsById(Long id)
    {
        return yiyaClosingMethodsMapper.deleteYiyaClosingMethodsById(id);
    }

    @Override
    public List<YiyaClosingMethods> selectByMainClosingEntriesIds(List<Long> mainClosingEntriesIds) {
        return yiyaClosingMethodsMapper.selectByMainClosingEntriesIds(mainClosingEntriesIds);
    }

    @Transactional(rollbackFor=Exception.class)
    public AjaxResult payMoney(PayMoneyRequest payMoneyRequest) throws Exception {
        Long clinicPersonId = payMoneyRequest.getClinicPersonId();
        Long mainClosingEntriesId = payMoneyRequest.getMainClosingEntriesId();
        Long billingMainId = payMoneyRequest.getBillingMainId();
        String charge = payMoneyRequest.getCharge();
        String closingRemarks = payMoneyRequest.getClosingRemarks();
        Boolean aReturn = payMoneyRequest.getReturn();
        if (clinicPersonId != null && clinicPersonId > 0 && mainClosingEntriesId != null && mainClosingEntriesId > 0 && billingMainId != null && billingMainId > 0 && !"".equals(charge) && aReturn != null) {
            List<ModeAndMoney> modeAndMonies = payMoneyRequest.getModeAndMonies();
            if (modeAndMonies.size() > 0) {
                modeAndMonies.forEach(r -> {
                    YiyaClosingMethods yiyaClosingMethods = new YiyaClosingMethods();
                    yiyaClosingMethods.setClinicPersonId(clinicPersonId);
                    yiyaClosingMethods.setMainClosingEntriesId(mainClosingEntriesId);
                    yiyaClosingMethods.setClosingMode(r.getClosingMode());
                    if (aReturn) { //是退费
                        yiyaClosingMethods.setClosingMoney(r.getClosingMoney().negate());
                    } else { //不是退费
                        yiyaClosingMethods.setClosingMoney(r.getClosingMoney());
                    }
                    yiyaClosingMethodsMapper.insertYiyaClosingMethods(yiyaClosingMethods);
                    if ("储值划扣".equals(r.getClosingMode())){ //todo 如果结账金额为储值划扣 需要修改会员信息里的储值金额 并且添加会员流水

                    }
                });
                // 修改结账单状态为已结账 //todo 状态枚举
                YiyaMainClosingEntries yiyaMainClosingEntriesResponse = yiyaMainClosingEntriesService.selectYiyaMainClosingEntriesById(mainClosingEntriesId);
                YiyaMainClosingEntries yiyaMainClosingEntriesRequest = new YiyaMainClosingEntries();
                yiyaMainClosingEntriesRequest.setId(mainClosingEntriesId);
                yiyaMainClosingEntriesRequest.setCharge(charge);
                yiyaMainClosingEntriesRequest.setClosingRemarks(closingRemarks);
                yiyaMainClosingEntriesRequest.setBillStatus(3); //已结账状态
                yiyaMainClosingEntriesService.updateYiyaMainClosingEntries(yiyaMainClosingEntriesRequest);
                YiyaBillingMain yiyaBillingMain = yiyaBillingMainService.selectYiyaBillingMainById(billingMainId);
                BigDecimal beforeOwingAmount = yiyaBillingMain.getOwingAmount(); // 之前的欠费
                BigDecimal beforePayAmount = yiyaBillingMain.getPayAmount(); // 之前的缴费
                if (yiyaMainClosingEntriesResponse.getType() == 1) { // 首开单缴费
                    BigDecimal owingAmount = yiyaBillingMain.getReceivable().subtract(yiyaMainClosingEntriesResponse.getThisPay());
                    setMainStatus(yiyaBillingMain, owingAmount);
                    yiyaBillingMainService.updateYiyaBillingMain(yiyaBillingMain);
                } else {
                    if (!aReturn) { //不是退费
                        yiyaBillingMain.setPayAmount(yiyaBillingMain.getPayAmount().add(yiyaMainClosingEntriesResponse.getThisPay()));//非首开单缴费 原缴费+此次缴费
                        BigDecimal owingAmount = yiyaBillingMain.getOwingAmount().subtract(yiyaMainClosingEntriesResponse.getThisPay());
                        setMainStatus(yiyaBillingMain, owingAmount);
                        yiyaBillingMainService.updateYiyaBillingMain(yiyaBillingMain);
                    }
                }
                YiyaItemBilling yiyaItemBilling = new YiyaItemBilling();
                yiyaItemBilling.setBillingMainId(billingMainId);
                List<YiyaItemBilling> yiyaItemBillings = yiyaItemBillingService.selectYiyaItemBillingList(yiyaItemBilling);
                // mainClosingEntriesId 查出 结账流水项目关系转成 项目id map
                YiyaClosingWaterRelation yiyaClosingWaterRelationRequest = new YiyaClosingWaterRelation();
                yiyaClosingWaterRelationRequest.setMainClosingEntriesId(mainClosingEntriesId);
                Map<Long, YiyaClosingWaterRelation> closingWaterRelationMap = yiyaClosingWaterRelationService.selectYiyaClosingWaterRelationList(yiyaClosingWaterRelationRequest).stream().collect(Collectors.toMap(YiyaClosingWaterRelation::getItemBillingId, a -> a, (k1, k2) -> k1));
                yiyaItemBillings.forEach(ib -> {
                    YiyaClosingWaterRelation yiyaClosingWaterRelation = closingWaterRelationMap.get(ib.getId());
                    if (!aReturn) { //不是退费
                        if (yiyaClosingWaterRelation != null) {
                            //更新项目已收 原已收+本次收费+储值划扣金
                            ib.setProjectReceived(ib.getProjectReceived().add(yiyaClosingWaterRelation.getThisPay()).add(yiyaClosingWaterRelation.getStoredDeductPrice()));
                            //更新项目欠费 原欠费-本次收费-储值划扣金
                            if (yiyaMainClosingEntriesResponse.getType() == 1) { // 首开单缴费
                                BigDecimal arrearage = ib.getProjectReceivable().subtract(yiyaClosingWaterRelation.getThisPay()).subtract(yiyaClosingWaterRelation.getStoredDeductPrice());
                                setItemStatus(ib, arrearage);
                            } else {
                                BigDecimal arrearage = ib.getProjectArrearage().subtract(yiyaClosingWaterRelation.getThisPay()).subtract(yiyaClosingWaterRelation.getStoredDeductPrice());
                                setItemStatus(ib, arrearage);
                            }
                            yiyaItemBillingService.updateYiyaItemBilling(ib);
                        }
                    } else { //是退费
                        if (yiyaClosingWaterRelation != null) {
                            //更新项目已收
                            BigDecimal receivedMoney = ib.getProjectReceived().subtract(yiyaClosingWaterRelation.getThisPay()).subtract(yiyaClosingWaterRelation.getStoredDeductPrice());
                            ib.setProjectReceived(receivedMoney); //项目已收
                            ib.setProjectReceivable(receivedMoney); //项目应收=项目已收
                            ib.setProjectArrearage(BigDecimal.ZERO); //项目欠款为0
                            ib.setStatus(3); //已退款
                            yiyaItemBillingService.updateYiyaItemBilling(ib);
                        }
                    }
                });
                if (aReturn) { //是退费  再修改主单相关金额
                    List<YiyaItemBilling> afterUpdateItems = yiyaItemBillingService.selectYiyaItemBillingList(yiyaItemBilling);
                    yiyaBillingMain.setPayAmount(new BigDecimal(afterUpdateItems.stream().mapToDouble(r -> r.getProjectReceived().doubleValue()).sum()));//缴费
                    yiyaBillingMain.setReceivable(new BigDecimal(afterUpdateItems.stream().mapToDouble(r -> r.getProjectReceivable().doubleValue()).sum())); //应收
                    BigDecimal owingAmount = new BigDecimal(afterUpdateItems.stream().mapToDouble(r -> r.getProjectArrearage().doubleValue()).sum());//欠费
                    setMainStatus(yiyaBillingMain, owingAmount);
                    yiyaBillingMainService.updateYiyaBillingMain(yiyaBillingMain);
                }
                YiyaBillingMain yiyaBillingMainAfter = yiyaBillingMainService.selectYiyaBillingMainById(billingMainId);
                BigDecimal afterOwingAmount = yiyaBillingMainAfter.getOwingAmount(); // 之后欠费
                BigDecimal afterPayAmount = yiyaBillingMainAfter.getPayAmount(); // 之后缴费
                YiyaClinicPerson yiyaClinicPersonResponse = yiyaClinicPersonService.selectYiyaClinicPersonById(yiyaBillingMain.getClinicPersonId());
                YiyaMarketReservation yiyaMarketReservationResponse = yiyaMarketReservationService.selectYiyaMarketReservationById(yiyaClinicPersonResponse.getMarketReservationId());
                YiyaMarketReservation yiyaMarketReservationRequest = new YiyaMarketReservation();
                YiyaClinicPerson yiyaClinicPersonRequest = new YiyaClinicPerson();
                yiyaClinicPersonRequest.setId(yiyaClinicPersonResponse.getId());
                if(yiyaMainClosingEntriesResponse.getType() == 1){
                    //首开单，以事后状态为准
                    yiyaClinicPersonRequest.setOverMoney(yiyaClinicPersonResponse.getOverMoney().add(afterPayAmount));
                    yiyaClinicPersonRequest.setArrearage(yiyaClinicPersonResponse.getArrearage().add(afterOwingAmount));    
                }else{
                    yiyaClinicPersonRequest.setOverMoney(yiyaClinicPersonResponse.getOverMoney().add(afterPayAmount).subtract(beforePayAmount));
                    yiyaClinicPersonRequest.setArrearage(yiyaClinicPersonResponse.getArrearage().add(afterOwingAmount).subtract(beforeOwingAmount));    
                }
                if (!"已开单".equals(yiyaClinicPersonResponse.getBillingState())) {
                    yiyaClinicPersonRequest.setBillingState("已开单");
                }
                if (yiyaMarketReservationResponse != null && !"已开单".equals(yiyaMarketReservationResponse.getBillingState())) {
                    yiyaMarketReservationRequest.setId(yiyaMarketReservationResponse.getId());
                    yiyaMarketReservationRequest.setBillingState("已开单");
                    yiyaMarketReservationRequest.setTurnoverMoney(yiyaBillingMainAfter.getReceivable()); // 成交金额为 首单应收金额
                    yiyaMarketReservationRequest.setCheckoutTime(now());
                    yiyaMarketReservationService.updateYiyaMarketReservation(yiyaMarketReservationRequest);
                }
                yiyaClinicPersonService.updateYiyaClinicPerson(yiyaClinicPersonRequest);

                // 生成统计表信息  yiya_statistics_item yiya_statistics_mode_pay
                YiyaClosingMethods yiyaClosingMethodsRequest = new YiyaClosingMethods();
                yiyaClosingMethodsRequest.setMainClosingEntriesId(yiyaMainClosingEntriesResponse.getId());
                List<YiyaClosingMethods> yiyaClosingMethodsResponse = yiyaClosingMethodsMapper.selectYiyaClosingMethodsList(yiyaClosingMethodsRequest);
                yiyaClosingMethodsResponse.forEach(cm -> {
                    YiyaStatisticsModePay yiyaStatisticsModePayRequset = new YiyaStatisticsModePay();
                    yiyaStatisticsModePayRequset.setMainClosingEntriesId(cm.getMainClosingEntriesId());
                    yiyaStatisticsModePayRequset.setClosingMethodsId(cm.getId());
                    yiyaStatisticsModePayRequset.setMarketReservationId(yiyaBillingMainAfter.getMarketReservationId());
                    yiyaStatisticsModePayRequset.setClinicPersonId(yiyaBillingMainAfter.getClinicPersonId());
                    yiyaStatisticsModePayRequset.setName(yiyaClinicPersonResponse.getName());
                    yiyaStatisticsModePayRequset.setPhoneNumber1(yiyaClinicPersonResponse.getPhoneNumber());
                    yiyaStatisticsModePayRequset.setClinic(yiyaBillingMainAfter.getClinic());
                    yiyaStatisticsModePayRequset.setTc(yiyaBillingMainAfter.getTc());
                    yiyaStatisticsModePayRequset.setBillingPerson(yiyaMainClosingEntriesResponse.getBillingPerson());
                    yiyaStatisticsModePayRequset.setClosingMoney(cm.getClosingMoney());
                    yiyaStatisticsModePayRequset.setClosingMode(cm.getClosingMode());
                    yiyaStatisticsModePayRequset.setMarketAffiliationPerson(yiyaMarketReservationResponse != null ? yiyaMarketReservationResponse.getAffiliationPerson() : " ");
                    yiyaStatisticsModePayRequset.setClosingTime(cm.getClosingTime());
                    yiyaStatisticsModePayRequset.setPlungeTime(getPlungeTime(cm.getClosingTime()));
                    yiyaStatisticsModePayService.insertYiyaStatisticsModePay(yiyaStatisticsModePayRequset);
                });
                Map<Long, YiyaChargeProject> yiyaChargeProjectMap = yiyaChargeProjectService.selectByIds(yiyaItemBillings.stream().map(YiyaItemBilling::getItemId).collect(Collectors.toList())).stream().collect(Collectors.toMap(YiyaChargeProject::getId, a -> a, (k1, k2) -> k1));
                yiyaItemBillingService.selectYiyaItemBillingList(yiyaItemBilling).forEach(l -> {
                    YiyaClosingWaterRelation yiyaClosingWaterRelation = closingWaterRelationMap.get(l.getId());
                    YiyaChargeProject yiyaChargeProject = yiyaChargeProjectMap.get(l.getItemId());
                    YiyaStatisticsItem yiyaStatisticsItemRequest = new YiyaStatisticsItem();
                    yiyaStatisticsItemRequest.setMainClosingEntriesId(mainClosingEntriesId);
                    yiyaStatisticsItemRequest.setItemBillingId(l.getId());
                    yiyaStatisticsItemRequest.setMarketReservationId(yiyaBillingMainAfter.getMarketReservationId());
                    yiyaStatisticsItemRequest.setClinicPersonId(yiyaBillingMainAfter.getClinicPersonId());
                    yiyaStatisticsItemRequest.setName(yiyaClinicPersonResponse.getName());
                    yiyaStatisticsItemRequest.setPhoneNumber1(yiyaClinicPersonResponse.getPhoneNumber());
                    yiyaStatisticsItemRequest.setClinic(yiyaBillingMainAfter.getClinic());
                    yiyaStatisticsItemRequest.setDoctor(l.getDoctor());
                    yiyaStatisticsItemRequest.setTc(yiyaBillingMainAfter.getTc());
                    yiyaStatisticsItemRequest.setBillingPerson(yiyaMainClosingEntriesResponse.getBillingPerson());
                    yiyaStatisticsItemRequest.setItemId(l.getItemId());
                    yiyaStatisticsItemRequest.setItemName(l.getItemName());
                    yiyaStatisticsItemRequest.setFirstProject(yiyaChargeProject.getFirstProjiect());
                    yiyaStatisticsItemRequest.setItemType(yiyaChargeProject.getType());
                    yiyaStatisticsItemRequest.setUnit(!"".equals(l.getUnit()) ? l.getUnit() : " ");
                    yiyaStatisticsItemRequest.setUnitPrice(l.getUnitPrice());
                    yiyaStatisticsItemRequest.setCount(l.getCount());
                    yiyaStatisticsItemRequest.setThisPay(aReturn ? yiyaClosingWaterRelation.getThisPay().negate() : yiyaClosingWaterRelation.getThisPay());
                    yiyaStatisticsItemRequest.setMarketAffiliationPerson(yiyaMarketReservationResponse != null ? yiyaMarketReservationResponse.getAffiliationPerson() : " ");
                    yiyaStatisticsItemRequest.setClosingTime(yiyaClosingMethodsResponse.get(0).getClosingTime());
                    yiyaStatisticsItemRequest.setPlungeTime(getPlungeTime(yiyaClosingMethodsResponse.get(0).getClosingTime()));
                    yiyaStatisticsItemService.insertYiyaStatisticsItem(yiyaStatisticsItemRequest);
                });
                return AjaxResult.success();
            } else {
                return AjaxResult.error();
            }
        } else {
            return AjaxResult.error();
        }
    }

    private void setItemStatus(YiyaItemBilling ib, BigDecimal arrearage) {
        ib.setProjectArrearage(arrearage);
        //更新项目状态 欠费为0 状态为已结清1 欠费!=0 状态为欠费2
        if (arrearage.compareTo(BigDecimal.ZERO) == 0) { // 如果欠费为0
            ib.setStatus(1); //状态改为已结清
        } else {
            ib.setStatus(2); //状态改为已欠费
        }
    }

    private void setMainStatus(YiyaBillingMain yiyaBillingMain, BigDecimal owingAmount) {
        yiyaBillingMain.setOwingAmount(owingAmount);//更新欠费 原欠费-此次缴费
        //更新状态 欠费为0 状态为已结清2 欠费!=0 状态为未结清1
        if (owingAmount.compareTo(BigDecimal.ZERO) == 0) { // 如果欠费为0
            yiyaBillingMain.setStatus(2); //状态改为已结清
        } else {
            yiyaBillingMain.setStatus(1); //状态改为未结清
        }
    }

    private Date getPlungeTime(Date closingTime) {
        //得到一个Calendar实例
        Calendar calendar = Calendar.getInstance();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String pre = simpleDateFormat.format(closingTime);
        String endTime = pre.substring(0, 10) + " 16:00:00"; // 当天的下午4点
        calendar.add(Calendar.DATE, 1);
        Date tomorrow = calendar.getTime();
        String tomorrowPre = simpleDateFormat.format(tomorrow);
        String tomorrowZeroTime = tomorrowPre.substring(0, 10) + " 00:00:00";
        try {
            Date endDate = simpleDateFormat.parse(endTime);// 当天的下午4点 date
            return endDate.after(closingTime) ? closingTime : simpleDateFormat.parse(tomorrowZeroTime); //第二天 00:00:00
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            return closingTime;
        }
    }
}
